import {
  computed,
  defineAsyncComponent,
  defineComponent,
  ref,
  watch,
  type PropType,
  type WritableComputedRef,
} from "vue";
import Table, { type TableProps } from "ant-design-vue/es/table";
import type { ProColumnType } from "../interface";
import { Button } from "ant-design-vue";
import { renderDescVal } from "../utils/renderDesc";
import { getValue } from "../utils";
import useControl from "../add-and-detail/useControl";
import { usePagination } from "vue-request";
const AddAndDetail = defineAsyncComponent(() => import("../add-and-detail"));

export type ProTableExpose = {
  /**刷新数据(再次请求，不改变参数) */
  reload: () => void;
  /** 重置分页参数 */
  resetPageFields: () => void;
  /** 当前页码 */
  current: WritableComputedRef<number, number>;
  /** 每页条数 */
  pageSize: WritableComputedRef<number, number>;
};
export type ProTableProps = {
  columns: ProColumnType<any>[];
  request: () => Promise<
    {
      /** 数据总条数 */
      total: number;
      /** 当前页码 */
      current: number;
      /** 每页显示条数 */
      pageSize: number;
    } & {
      /** 数据列表，键名为动态字符串，值为任意类型数组 */
      [listKey: string]: any[];
    }
  >;
  tableProps: TableProps;
  mode: "read" | "write";
  pageSettings: {
    currentKey?: string;
    pageSizeKey?: string;
    totalKey?: string;
    totalPageKey?: string;
    listKey?: string;
    defaultPageSize?: number;
    defaultCurrent?: number;
  };
};

export default defineComponent({
  name: "ProTable",
  props: {
    /** 表格列配置 */
    columns: {
      required: true,
      type: Array as PropType<ProTableProps["columns"]>,
      default: () => [],
    },
    /** 请求数据的函数 */
    request: {
      required: true,
      type: Function as PropType<
        (params: {
          current: number;
          pageSize: number;
        }) => ProTableProps["request"]
      >,
    },
    /** 分页配置 */
    pageSettings: {
      type: Object as PropType<ProTableProps["pageSettings"]>,
      default: () => ({}),
    },
    /** 表格组件的属性配置 */
    tableProps: {
      type: Object as PropType<ProTableProps["tableProps"]>,
      default: () => ({}),
    },
    /** 表格操作模式，read为只读模式，write为表单编辑模式 */
    mode: {
      type: String as PropType<ProTableProps["mode"]>,
      default: "read",
    },
  },
  emits: {
    /** 保存数据 */
    save: (e: {
      index: number;
      data: Record<string, any>;
      type: "add" | "edit" | "del";
    }) => {
      return true; //类型/值校验
    },
  },
  setup(props, ctx) {
    const { open, currRow, currIdx, title, mode, resetForm } = useControl();
    const _request = computed(() => props.request);

    const _pageSettings = computed(() => {
      return {
        currentKey: "current",
        pageSizeKey: "pageSize",
        totalKey: "total",
        totalPageKey: "totalPage",
        listKey: "result",
        defaultPageSize: 10,
        defaultCurrent: 1,
        ...props.pageSettings,
      };
    });

    const _pagination = computed(() => ({
      total: total.value,
      current: current.value,
      pageSize: pageSize.value,
    }));

    const {
      /**请求得到的整体内容（Promise结果） */
      data,
      /**请求 */
      run,
      loading,
      /**值的改变也会触发请求 */
      current,
      /**（值的改变也会触发请求) */
      pageSize,
      total,
    } = usePagination<ReturnType<ProTableProps["request"]>>(
      // _request.value,
      (pagesParams: { pageSize: number; current: number }) => {
        return _request.value({ ...pagesParams });
      },
      {
        defaultParams: [
          {
            [_pageSettings.value.currentKey]:
              _pageSettings.value.defaultCurrent,
            [_pageSettings.value.pageSizeKey]:
              _pageSettings.value.defaultPageSize,
          },
        ],
        pagination: _pageSettings.value,
      }
    );

    const add_columns = computed(() => {
      const cols = [] as ProColumnType<any>[];

      (
        (props.tableProps.columns || props.columns) as ProColumnType<any>[]
      ).forEach((item) => {
        if (!item.hideInTable) {
          cols.push({
            ...item,
            customRender:
              props.mode === "read"
                ? item.textRender ??
                  (({ text, record, index }) =>
                    renderDescVal(
                      item,
                      getValue(record, item.dataIndex),
                      "jsx"
                    ))
                : item.fieldRender,
          });
        }
      });
      return cols;
    });

    const table_columns = computed(() => {
      // if(props.mode === "write") return []
      const cols = [...add_columns.value];

      if (props.mode === "write") {
        cols.push({
          title: "操作",
          dataIndex: "_action",
          width: 100,
          customRender: ({ text, record, index }) => {
            return (
              <div class="flex">
                <Button
                  size="small"
                  type="link"
                  onClick={() => {
                    currIdx.value = index;
                    currRow.value = record;
                    title.value = "编辑";
                    open.value = true;
                  }}
                >
                  编辑
                </Button>
                <Button
                  size="small"
                  danger
                  type="link"
                  onClick={() => {
                    ctx.emit("save", { index, data: record, type: "del" });
                  }}
                >
                  删除
                </Button>
              </div>
            );
          },
        });
      }

      return cols;
    });

    const handleTableChange = (
      pag: { pageSize?: number; current?: number },
      filters: any,
      sorter: any
    ) => {
      run({
        // results: pag.pageSize,
        [_pageSettings.value.currentKey]: pag?.current,
        [_pageSettings.value.pageSizeKey]: pag?.pageSize,
        // sortField: sorter.field,
        // sortOrder: sorter.order,
        ...filters,
      });
    };

    const reload = () => {
      run({
        [_pageSettings.value.currentKey]: current.value,
        [_pageSettings.value.pageSizeKey]: pageSize.value,
      });
    };

    const resetPageFields = () => {
      current.value = _pageSettings.value.defaultCurrent; //
      // pageSize.value = _pageSettings.value.defaultPageSize;// 不重置每页条数（值的改变也会触发请求)
    };

    ctx.expose({
      current,
      pageSize,
      resetPageFields,
      reload,
    } as ProTableExpose);

    // =================================
    const addRow = () => {
      resetForm();
      currIdx.value = data.value?.[_pageSettings.value.listKey]?.length || 0;
      open.value = true;
    };

    return () => (
      <div class="pro-table">
        {/* <pre>{JSON.stringify(_columns.value, null, 2)}</pre> */}
        {/* <div>{JSON.stringify(data.value)}</div> */}
        <Table
          {...props.tableProps}
          // size={props.mode === "read" ? "small" : undefined}
          loading={props.mode === "read" ? loading.value : false}
          columns={table_columns.value}
          dataSource={
            props.tableProps.dataSource ||
            data.value?.[_pageSettings.value.listKey] ||
            []
          }
          pagination={
            props.mode === "read"
              ? props.tableProps.pagination ?? _pagination.value
              : false
          }
          rowKey={
            props.mode === "read" ? props.tableProps.rowKey || "id" : undefined
          }
          onChange={handleTableChange}
        ></Table>

        {props.mode === "write" && (
          <div>
            <AddAndDetail
              mode="write"
              v-model:open={open.value}
              title={title.value}
              request={() => Promise.resolve(currRow.value)}
              columns={add_columns.value}
              onFinish={(v) => {
                ctx.emit("save", {
                  index: currIdx.value,
                  data: v,
                  type: currRow.value ? "edit" : "add",
                });
                return Promise.resolve(true);
              }}
            />
            <Button block onClick={addRow}>
              +
            </Button>
          </div>
        )}
      </div>
    );
  },
});
